/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-14 09:40:11
 * @LastEditTime: 2021-07-16 14:02:37
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#ifndef BSP_DRIVERS_E2000_TIMER_TACHO_H
#define BSP_DRIVERS_E2000_TIMER_TACHO_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "ft_types.h"
#include "ft_debug.h"
#include "ft_error_code.h"

typedef enum
{
    /* timer mode */
    TIMER_WORK_MODE_TIMER = 0,
    TIMER_WORK_MODE_TACHO,
    TIMER_WORK_MODE_CAPTURE
}TimerTachoModeType;

typedef enum
{
    TIMER_FREE_RUN = 0,
    TIMER_RESTART
}TimerWorkModeType;

typedef enum
{
    TIMER_32_BITS = 0,
    TIMER_64_BITS
}TimerBitsType;

typedef enum
{
    TIMER_ONCE_CMP = 0,
    TIMER_CYC_CMP
}TimerCmpType;

typedef enum
{
    TACHO_EVENT_OVER = 0,
    TACHO_EVENT_UNDER,
    TIMER_EVENT_ROLL_OVER,
    TIMER_EVENT_ONCE_CMP,
    TIMER_EVENT_CYC_CMP,
    TACHO_EVENT_CAPTURE,
    
    MAX_TIMER_TACHO_EVENT
}TimerTachoEventType;

typedef enum
{
    TACHO_FALLING_EDGE = 0,
    TACHO_RISING_EDGE,
    TACHO_DOUBLE_EDGE
}TachoEdgeType;

typedef struct 
{
    u32     Id;        /* id of timer tacho */
    char    Name[12];  /* instance name */
    u32     IrqPriority; /* intr priority */
    u32     WorkMode;  /* timer/tacho/capture mode */
    /* for timer function */
    u32     TimerMode; /* free-run/restart */
    u32     TimerBits; /* 32/64 bits */
    u32     CmpType; /* once/cycle cmp */
    boolean ClearCnt;  /* clear timer counts */
    boolean ForceLoad; /* start count from start val */
    /* for tacho function */
    u32     EdgeMode; /* rising/falling/double */
    u32     Debounce; /* jitter level */
    u32     PlusNum;  /* plus_num of period to calculate rpm */
    u32     CaptueCnt; /* in capture mode, when cnt reach this val, intr asserted */
}TimerTachoConfig;

typedef void (*TimerEventHandler)(void *pCtrl);

typedef struct
{
    TimerTachoConfig     Config;
    boolean              IsReady;
    TimerEventHandler    EvtHandlers[MAX_TIMER_TACHO_EVENT];
}TimerTachoCtrl;

/* Time & Tacho API */
void TimerSoftwareReset(TimerTachoCtrl *pCtrl);
u32 TimerGetInterruptMask(TimerTachoCtrl *pCtrl);
void TimerStart(TimerTachoCtrl *pCtrl);
void TimerStop(TimerTachoCtrl *pCtrl);
u32 TimerSwithMode(TimerTachoCtrl *pCtrl, TimerTachoConfig *pNewConfig);
void TimerDefaultEvtCallback(void *pPara);
void TimerRegisterEvtCallback(TimerTachoCtrl *pCtrl, 
                              TimerTachoEventType EvtType, 
                              TimerEventHandler Callback);
void TimeSettingDump(const TimerTachoCtrl *pCtrl);

/* Timer API */
u32 TimerInit(TimerTachoCtrl *pCtrl, const TimerTachoConfig *pConfig);
void TimerGetDefConfig(u32 TimerID, TimerTachoConfig *pConfig);
u32 TimerSetPeriod32(TimerTachoCtrl *pCtrl, u32 ticks);
u32 TimerSetPeriod64(TimerTachoCtrl *pCtrl, u64 ticks);
u32 TimerGetCurCnt32(TimerTachoCtrl *pCtrl);
u64 TimerGetCurCnt64(TimerTachoCtrl *pCtrl);
void TimerSetStartVal(TimerTachoCtrl *pCtrl, u32 cnt);

/* Tacho API */
u32 TachoInit(TimerTachoCtrl *pCtrl, const TimerTachoConfig *pConfig);
void TachoGetDefConfig(u32 TachoID, TimerTachoConfig *pConfig);
void TachoSetCntPeriod(TimerTachoCtrl *pCtrl, u32 ticks);
void TachoSetOverLimit(TimerTachoCtrl *pCtrl, u32 overLim);
void TachoSetUnderLimit(TimerTachoCtrl *pCtrl, u32 underLim);
u32 TachoGetFanRPM(TimerTachoCtrl *pCtrl);
u32 TachoGetCaptureCnt(TimerTachoCtrl *pCtrl);

#define TIMER_SUCCESS     FT_SUCCESS  
#define TIMER_INIT_FAILED FT_MAKE_ERRCODE(ErrModBsp, ErrBspTimer, 1)
#define TIMER_INVALID_PARM FT_MAKE_ERRCODE(ErrModBsp, ErrBspTimer, 2)

#define TIMER_DEBUG_TAG "TIMER"
#define TIMER_ERROR(format, ...)   FT_DEBUG_PRINT_E(TIMER_DEBUG_TAG, format, ##__VA_ARGS__)
#define TIMER_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(TIMER_DEBUG_TAG, format, ##__VA_ARGS__)
#define TIMER_DEBUG_D(format, ...) FT_DEBUG_PRINT_D(TIMER_DEBUG_TAG, format, ##__VA_ARGS__)

#ifdef __cplusplus
}
#endif

#endif // !